package com.re6g3y.game.core;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.mygdx.game.tools.PhysicsEditorShapeLibrary;
import com.re6g3y.game.Tile.Hexagonal.HexagonalMap;
import com.re6g3y.game.Tile.Hexagonal.mapGenerate.HexagonalChunk;
import com.re6g3y.game.Tile.Hexagonal.mapGenerate.HexagonalMapEditor;
import com.re6g3y.game.entity.Ship;
import com.re6g3y.game.entity.TextureEntityWithBody;
import com.re6g3y.game.mulitThread.WorldStepThread;
import com.re6g3y.game.mulitThread.MainAssigner;
import com.re6g3y.game.textureUitls.TextureLoader;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public class GameCore extends ApplicationAdapter {
    private GameCore(){}
    private static GameCore instance=new GameCore();
    public static GameCore getInstance(){
        return instance;
    }

    //need dispose
    public TextureLoader textureLoader;
    public MainAssigner ma;
    public WorldStepThread worldStepThread;
    public Batch batch;
    public World world;

    public HexagonalMap map;
    public Queue<Runnable> bathDrawQueue;
    public PhysicsEditorShapeLibrary physicsEditorShapeLibrary;
    public OrthographicCamera camera;
    public OrthographicCamera UIcamera;
    HexagonalMapEditor hexagonalMapEditor;
    public float detTime=1F;

    @Override
    public void create () {
        bathDrawQueue=new ConcurrentLinkedQueue<Runnable>();
        textureLoader=new TextureLoader();
        ma=new MainAssigner(8);
        batch=new SpriteBatch();
        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        UIcamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        new InputEven(camera);
        world=new World(Vector2.Zero,true);
        worldStepThread =new WorldStepThread(world);
        physicsEditorShapeLibrary=new PhysicsEditorShapeLibrary();
        map=new HexagonalMap();

        loadFont();
        pixmap = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Pixmap.Format.RGBA8888);


        hexagonalMapEditor =new HexagonalMapEditor(30);
    }

    @Override
    public void resize (int width, int height) {
        float x=camera.position.x;
        float y=camera.position.y;
        float z=camera.position.z;
        camera.setToOrtho(false,width,height);
        camera.position.set(x,y,z);
        x=UIcamera.position.x;
        y=UIcamera.position.y;
        z=UIcamera.position.z;
        UIcamera.setToOrtho(false,width,height);
        UIcamera.position.set(x,y,z);
    }

    @Override
    public void render () {
        super.render();
        detTime= Math.min(1f/20, Gdx.graphics.getDeltaTime());
//        Gdx.gl.glClearColor( 0, 0, 0, 1 );
        Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);

        //游戏主循环
        drawAll();

        worldStepThread.step(detTime,2,2);
        camera.update();
        batch.setProjectionMatrix( camera.combined );
        batch.begin();
        if(result==null) result = new Texture(pixmap);
        else result.draw(pixmap,0,0);
        batch.draw(result,-1920/2,-1030/2);

        while(!bathDrawQueue.isEmpty()){
            bathDrawQueue.poll().run();
        }
        batch.end();
        batch.setProjectionMatrix(UIcamera.combined );
        batch.begin();
        writeFPS();
        batch.end();
        worldStepThread.waitForFinish();
    }

    List<TextureEntityWithBody> textureEntityWithBodyList =new ArrayList<TextureEntityWithBody>();
    int tick=0;

    Pixmap pixmap ;
    Texture result=null;
    /**
     * 游戏主循环
     */
    private void drawAll(){
//        pixmap.setColor(0);
//        pixmap.fill();
//        pixmap.setColor(Color.ROYAL);
//

//        bathDrawQueue.add(new Runnable() {
//            @Override
//            public void run() {
//                for(final HexagonalChunk chunk:hexagonalMapEditor.getChunkByRange(center,10)){
//                    chunk.draw(batch);
//                }
//            }
//        });

        if(tick==0) {
            physicsEditorShapeLibrary.load(Gdx.files.internal("flare.xml").file(), "flare", 1);
            textureLoader.load("flare.png");
        }
        if((tick++)<100) {
            Texture texture = textureLoader.get("flare");
            Sprite sprite = new Sprite(texture);
//            if(tick<50)sprite.setColor(Color.RED);
            if((tick&1)==0)sprite.setAlpha(0.5f);
            Body body = physicsEditorShapeLibrary.createBody("flare", new Vector2(MathUtils.random(3000f),MathUtils.random(3000f)), world);
            body.setBullet(true);
            Ship textureEntity = new Ship();
            textureEntity.setSpriteAndBody(sprite, body);
            textureEntityWithBodyList.add(textureEntity);
            textureEntity.lookToTarget(new Vector2(MathUtils.random(3000f),MathUtils.random(3000f)));
        }
//        System.out.println(tick);

        final Vector2 now=new Vector2(1000* MathUtils.sin(tick/360F),1000* MathUtils.cos(tick/360F));
        for(int i = 0; i< textureEntityWithBodyList.size(); i++){
            final Ship s=(Ship) textureEntityWithBodyList.get(i);
//            s.lookToTarget(textureEntityWithBodyList.get((i+1)%textureEntityWithBodyList.size()).body.getPosition());
            s.lookToTarget();
            s.moveForward();
            s.stabilize();
//            Set<Object> tileSet=map.getTileEntitysByPointAndRange(s.getBody().getPosition(),10,300);
//            for(Object object:tileSet){
//                final HexagonalTile tile=(HexagonalTile)object;
//                bathDrawQueue.add(new Runnable() {
//                    @Override
//                    public void run() {
//                        tile.draw(batch);
//                    }
//                });
//            }
            bathDrawQueue.add(new Runnable() {
                @Override
                public void run() {
                    s.draw(batch);
                }
            });
//            pixmap.drawLine((int)s.body.getPosition().x, pixmap.getHeight()-(int) s.body.getPosition().y, (int) s.target.x, pixmap.getHeight()-(int)s.target.y);
//            pixmap.drawLine((int)(s.body.getPosition().x)+1920/2,1080/2-(int)(s.body.getPosition().y),(int)(now.x)+1920/2,1080/2-(int)(now.y));
//            System.out.println(now);
            now.set(s.body.getPosition());
        }
//
//        for(final TextureEntityWithBody t: textureEntityWithBodyList){
//            bathDrawQueue.add(new Runnable() {
//                @Override
//                public void run() {
//                    t.draw(batch);
//                }
//            });
//        }

//        if(center.x!=camera.position.x||center.y!=camera.position.y){
            center.set(camera.position.x,camera.position.y);
//            hexagonalMapEditor.getTileByRange(center,(int)(1100/HexagonalMap.innerRadius/1.8*camera.zoom));
//        }


//        Box2DDebugRenderer box2DDebugRenderer=new Box2DDebugRenderer();
//        box2DDebugRenderer.render(world, camera.combined);
//        box2DDebugRenderer.dispose();

        ma.notifyAndWaitFinish();
    }
    Vector2 center=new Vector2(0,0);

    @Override
    public void pause () {
    }

    @Override
    public void resume () {
    }

    @Override
    public void dispose () {
        textureLoader.dispose();
        batch.dispose();
        ma.dispose();
    }



    FreeTypeFontGenerator gen;
    BitmapFont font;

    private void loadFont(){

        gen = new FreeTypeFontGenerator( Gdx.files.internal("msjh.ttf"));
        FreeTypeFontGenerator.FreeTypeFontParameter par=new FreeTypeFontGenerator.FreeTypeFontParameter();
        par.color=Color.CYAN;
        par.size=20;

        par.characters+="非并行";
        par.borderWidth=3f;
        par.borderColor=Color.PINK;

        par.shadowColor=Color.NAVY;
        par.shadowOffsetX=3;
        par.shadowOffsetY=3;

        font = gen.generateFont(par);
    }
    private void writeFPS(){
//        font.draw(batch, "并行",3, 20*3);
//        font.draw(batch, "ALL:"+calnum,3, 20*2);
//        calnum=0;
        font.draw(batch, "FPS:" + Gdx.graphics.getFramesPerSecond(),3, 60);
        font.draw(batch, "X:" + camera.position.x+" Y:"+camera.position.y,3, 30);
    }
}
